/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.worlds.lua;

import java.awt.Color;
import java.io.IOException;
import net.worlds.Main;
import net.worlds.Util;
import net.worlds.World;
import net.worlds.object.GameObject;
import org.jbox2d.common.Vec2D;
import se.krka.kahlua.luaj.compiler.LuaCompiler;
import se.krka.kahlua.vm.JavaFunction;
import se.krka.kahlua.vm.LuaCallFrame;
import se.krka.kahlua.vm.LuaClosure;
import se.krka.kahlua.vm.LuaState;


public class GlobalFunctions {
    public static class Sleep implements JavaFunction
    {
        public int call(LuaCallFrame callFrame, int nArguments) {
            if(nArguments  == 0)
                Thread.yield();
            else
            {
                if(!Util.isDouble(callFrame.get(0).toString()))
                    throw new RuntimeException("Argument should be the number of seconds");
                double d = (Double) callFrame.get(0);
                /*if(Thread.currentThread().getName().contains("Script_") && d > 0.5)
                {
                    try {
                        if(Main.getPlayer() != null && !Main.canUseTools)
                        {
                            if(!Main.getPlayer().hasChild("UI"))
                            {
                                UILabel l = (UILabel) Main.getGame().getCurrentWorld().createObject("UILabel");
                                l.setProp("Text", "Buildism Warning: This game is using a now-unsupported scripting technique that will be removed soon. Please notify the creator.", true);
                                l.setProp("TextColor", new Color(0, 0, 0), true);
                                l.setProp("Position", new Vec2D(100, 100), true);
                                l.setProp("Parent", Main.getPlayer().getChild("UI"), true);
                            }
                        }
                        Main.log("Warning: Using sleep() for long periods of time in event handlers will be disabled on 8/1/11. Using os.time() is a more efficient, less buggy method in many cases; please use the forums if you need help.");
                    } catch (BuildismException ex) {
                        ex.printStackTrace();
                    }
                }*/
                int ms = (int) (d * 1000);
                try {
                    Thread.sleep(ms);
                } catch (InterruptedException ex) {
                    return 0;
                }
            }
            return 0;
        }
    }
    public static class Vec2DFunction implements JavaFunction
    {

        public int call(LuaCallFrame callFrame, int nArguments) {
            if(nArguments != 2)
                throw new RuntimeException("Vec2D() requires 2 arguments");
            if(!Util.isVec2D(callFrame.get(0)+","+callFrame.get(1)))
                throw new RuntimeException("Vec2D() requires number arguments");
            double x = (Double) callFrame.get(0);
            double y = (Double) callFrame.get(1);
            callFrame.push(new Vec2D((float) x, (float) y));
            return 1;
        }
    }
    public static class ColorFunction implements JavaFunction
    {
        public int call(LuaCallFrame callFrame, int nArguments) {
            if(nArguments != 3)
                throw new RuntimeException("Color() requires 3 arguments");
            if(!Util.isColor(new String(callFrame.get(0)+","+callFrame.get(1)+","+callFrame.get(2))))
                throw new RuntimeException("Color() requires number arguments");
            double rd = (Double) callFrame.get(0);
            double gd = (Double) callFrame.get(1);
            double bd = (Double) callFrame.get(2);
            Color c = new Color((int) rd, (int) gd, (int) bd);
            callFrame.push(c);
            return 1;
        }
    }
    public static class LinkFunction implements JavaFunction
    {
        private LuaState state;
        private ScriptThread st;
        public LinkFunction(LuaState state, ScriptThread st)
        {
            this.state = state;
            this.st = st;
        }
        public int call(LuaCallFrame callFrame, int nArguments) {
            if(nArguments != 2 || !(callFrame.get(0) instanceof Event) || !(callFrame.get(1) instanceof LuaClosure))
                throw new RuntimeException("link() requires an event and a function");
            Event e = (Event) callFrame.get(0);
            LuaClosure f = (LuaClosure) callFrame.get(1);
            if(st != null)
                e.connect(st.script, st, state, f);
            else
                e.connect(null, null, state, f);
            if(st != null)
                st.linkedEvents.add(e);
            return 0;
        }

    }
    public static class CreateFunction implements JavaFunction
    {
        private World world;
        public CreateFunction(World w)
        {
            world = w;
        }
        public int call(LuaCallFrame callFrame, int nArguments) {
            if(nArguments != 1)
                throw new RuntimeException("create() requires 1 argument");
            if(!(callFrame.get(0) instanceof String))
                throw new RuntimeException("create() requires a string");
            String className = (String) callFrame.get(0);
            try
            {
                GameObject obj = world.createObject(className);
                callFrame.push(obj);
            }
            catch(Exception ex)
            {
                if(Main.debug)
                    ex.printStackTrace();
                throw new RuntimeException(className+" is not a valid object type");
            }
            return 1;
        }
    }
    public static class LoadstringFunction implements JavaFunction
    {
        public int call(LuaCallFrame callFrame, int nArguments) {
            if(nArguments != 1 || !(callFrame.get(0) instanceof String))
                throw new RuntimeException("loadstring() requires a string argument");
            try {
                LuaClosure c = LuaCompiler.loadstring((String) callFrame.get(0), "string: "+callFrame.get(1), callFrame.thread.state.getEnvironment());
                callFrame.push(c);
            } catch (IOException ex) {
                callFrame.pushNil();
                throw new RuntimeException(ex);
            }
            return 1;
        }
    };
    public static class GetGameFunction implements JavaFunction
    {
        private World world;
        public GetGameFunction(World w)
        {
            world = w;
        }
        public int call(LuaCallFrame callFrame, int nArguments) {
            callFrame.push(world.getRootObject());
            return 1;
        }
    }
}
